<?php

class Redirect
{
    const CACHE_ID = "redirects/redirects";

    private function __construct() {}

    public static function GetRedirectQuery( $query )
    {
        $result = null;
        if ( strpos($query, 'path=') === 0 )
        {
            $result = ltrim( substr($query, 5), '/' );
            unset($_GET['path']);
            $params = UrlHelper::GetParams( $query );
            if ( !empty($params) )
            {
                $_GET = array_merge($_GET, $params);
            }
            $_REQUEST = array_merge($_REQUEST, $_GET, $_POST);
        }
        return $result;
    }

    public static function HandleRequest( $query )
    {
        //Timer::Start("Redirect::HandleRequest");

        if ( is_null($query) )
        {
            $pageInfo = self::Get404PageInfo();
        }
        else
        {
            UrlHelper::SplitParams($query, $path, $params);

            $id = "redirects/action_".str_replace( "%2F", "", str_replace( "%3A", "", rawurlencode($query) ) );

            $cache = Core::Cache();
            $action = $cache->Get($id);
            if ( !empty($action) && isset($action['action']) )
            {
                if ( $action['action'] == "redirect" )
                {
                    self::DoRedirect( $action['url'] );
                }
                else if ( $action['action'] == "generate" )
                {
                    $pageInfo = Pages::GetLngPageInfo( $action['page_id'] );
                }
            }
            else
            {
                $path = rtrim($path, '/');
                if ( empty( $path ) )
                {
                    $pageInfo = Pages::GetPageInfo( "Index" );
                }
                else
                {
                    $pageInfo = self::GetPageInfo( $query );
                    if ( empty($params) || count($params) == UrlHelper::ParamsMatched($pageInfo->path, $query) )
                    {
                        $action = array("action" => "generate", "page_id" => $pageInfo->id);
                        Core::Cache()->Set($id, $action);
                    }
                }
            }
        }

        //Timer::Stop("Redirect::HandleRequest");

        $pathParts = isset($path) ? explode('/', $path) : array();
        $appName = '';

        if ($pathParts[0] == 'admin')
        {
            $appName = $pathParts[0];
        }

        Core::SetApplication( Core::CreateApplication( $appName ) );

        if ( Pages::IsPageSecure($pageInfo) )
        {
            self::RequireLogin($pageInfo);
        }
        
        if ( $pageInfo->id != "Ping" )
        {
            self::RequireSSLConnection( $pageInfo->sslRequired );
        }

        if ( !empty($pageInfo->params) )
        {
            foreach ($pageInfo->params as $paramName => $paramValue)
            {
                if ( !Request::HasParam($paramName) )
                {
                    Request::SetParam($paramName, $paramValue);
                }
            }
        }

        self::ActivateNgixCache( $pageInfo );

        if ( empty($pageInfo->phpFile) )
        {
            $page = Pages::CreatePage( $pageInfo->id );
            $page->Process();
            $page->Display();
        }
        else
        {
            require_once($pageInfo->phpFile);
        }
    }

    private static function DoRedirect( $redirectUrl, $statusCode = null )
    {
        $query = $_SERVER['QUERY_STRING'];
        $urlParts = explode('?', $query);

        if ( count($urlParts) > 1 && !empty($urlParts[1]) )
        {
            $redirectUrl .= '?' . $urlParts[1];
        }
        Util::Redirect( $redirectUrl, $statusCode );
    }

    private static function GetPageInfo( $query )
    {
        $pageInfo = Pages::GetPageInfoByUrl($query);
        if ( empty($pageInfo) )
        {
            $pageInfo = self::Get404PageInfo();
        }
        return $pageInfo;
    }

    private static function Get404PageInfo()
    {
        $pageInfo = Pages::GetPageInfo("Error404");
        return $pageInfo;
    }

    /**
     * Activates nginx cache due to page info attributes.
     * @param PageInfo $pageInfo
     */
    private static function ActivateNgixCache( PageInfo $pageInfo )
    {
        if ( $pageInfo->useNginxCache && defined( 'NGINX_CACHED_PAGE_ACTUAL_FOR' ) )
        {
            header("Expires: " . gmdate("D, d M Y H:i:s", strtotime( "+" . NGINX_CACHED_PAGE_ACTUAL_FOR ) ) . " GMT");
        }
        else
        {
            header("Expires: 0");
        }
    }

    /**
     * Checks is current connection is secure and redirects to secure/unsecure connection according to requireSSL parameter.
     *
     * @param boolean $requireSSL
     */
    public static function RequireSSLConnection( $requireSSL )
    {
        if ( $requireSSL === "both" )
        {
            return;
        }

        if ( $requireSSL === true )
        {
            Request::RedirectToHTTPS();
        }
        else
        {
            Request::RedirectToHTTP();
        }
    }

    public static function RequireLogin($pageInfo)
    {
        $user = Core::App()->GetUser();
        if ( !$user->IsAuthenticated() )
        {
            if (!Request::IsAjaxRequest())
            {
                $user->SetReturnUrl(Request::GetURL());
            }

            $user->PrepareLogin();

            $referer = Request::GetReferer();
            $siteHost = UrlHelper::GetHost(SITE_URL);
            $isInternalResource = preg_match("/^" . $siteHost . "/" , $referer) !== false;
            
            $loginUrl = ($isInternalResource) ? '' : $referer;

            if ( empty($loginUrl))
            {
                $loginUrl = (empty($pageInfo->loginUrl)) 
                              ? UrlHelper::GetAbsolutePath(Core::App()->GetUser()->GetLoginUrl()) 
                              : $pageInfo->loginUrl;
            }

            $loginPageInfo = Pages::GetPageInfoByUrl( $loginUrl );

            if ( Pages::IsPageSecure( $loginPageInfo ) )
            {
                $loginUrl = UrlHelper::GetAbsolutePath($user->GetLoginUrl());
                $loginPageInfo = Pages::GetPageInfoByUrl( $loginUrl );
            }

            if (!UrlHelper::IsPathAbsolute( $loginUrl))
            {
                $loginUrl = (($loginPageInfo->sslRequired) ? 'https://' : 'http://') . $siteHost . $loginUrl;
            }

            if ($loginUrl)
            {
                Request::Redirect($loginUrl);
            }
            else
            {
                Request::SetStatusCode(HttpStatus::UNAUTHORIZED);
                exit();
            }
        }
    }
}

?>
